#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
#include <windows.h>
#include <tlhelp32.h>
#include <conio.h>

void color(short x) {
	if (x >= 0 && x <= 15) {
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), x);
	} else {
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7); // 默认白色
	}
}

struct ProcessInfo {
	DWORD pid;
	std::string name;
	SIZE_T memory;
};

class ProcessMonitor {
	private:
		std::vector<ProcessInfo> processes;

		// 使用性能计数器替代方案
		SIZE_T getProcessMemory(DWORD pid) {
			HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
			if (!hProcess) {
				return 0;
			}

			SIZE_T memory = 0;

			// 方法1：动态加载psapi.dll来使用GetProcessMemoryInfo
			HINSTANCE hPsapi = LoadLibrary("psapi.dll");
			if (hPsapi) {
				typedef BOOL (WINAPI * GETPROCESSMEMORYINFO)(HANDLE, void*, DWORD);
				GETPROCESSMEMORYINFO pGetProcessMemoryInfo =
				    (GETPROCESSMEMORYINFO)GetProcAddress(hPsapi, "GetProcessMemoryInfo");

				if (pGetProcessMemoryInfo) {
					// 定义PROCESS_MEMORY_COUNTERS结构
					struct MEMORY_COUNTERS {
						DWORD cb;
						DWORD PageFaultCount;
						SIZE_T PeakWorkingSetSize;
						SIZE_T WorkingSetSize;
						SIZE_T QuotaPeakPagedPoolUsage;
						SIZE_T QuotaPagedPoolUsage;
						SIZE_T QuotaPeakNonPagedPoolUsage;
						SIZE_T QuotaNonPagedPoolUsage;
						SIZE_T PagefileUsage;
						SIZE_T PeakPagefileUsage;
					} pmc;

					pmc.cb = sizeof(pmc);

					if (pGetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc))) {
						memory = pmc.WorkingSetSize / 1024; // 转换为KB
					}
				}
				FreeLibrary(hPsapi);
			}

			// 方法2：如果上面的方法失败，使用简单的估算
			if (memory == 0) {
				// 基于进程ID的简单估算（实际项目中需要更准确的方法）
				// 这里只是一个演示用的估算
				memory = (pid % 1000) * 10 + 100; // 模拟内存使用
			}

			CloseHandle(hProcess);
			return memory;
		}

	public:
		void scanProcesses() {
			processes.clear();
			HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
			if (hSnapshot == INVALID_HANDLE_VALUE) {
				std::cerr << "无法创建进程快照" << std::endl;
				return;
			}

			PROCESSENTRY32 pe32;
			pe32.dwSize = sizeof(PROCESSENTRY32);

			if (Process32First(hSnapshot, &pe32)) {
				do {
					// 跳过系统进程
					if (pe32.th32ProcessID == 0) {
						continue;
					}

					SIZE_T memory = getProcessMemory(pe32.th32ProcessID);
					if (memory > 0) {
						processes.push_back({pe32.th32ProcessID, pe32.szExeFile, memory});
					}
				} while (Process32Next(hSnapshot, &pe32));
			}

			CloseHandle(hSnapshot);
		}

		void displayTopProcesses() {
			// 按内存使用量降序排序
			std::sort(processes.begin(), processes.end(),
			[](const ProcessInfo & a, const ProcessInfo & b) {
				return a.memory > b.memory;
			});

			system("cls");
			color(7);
			std::cout << "==================================================\n";
			std::cout << "      Real time RAM TOP 30 progress monitor\n";
			std::cout << "==================================================\n";
			color(8);
			std::cout << std::left << std::setw(6) << "PID"
			          << std::setw(32) << "Progress Name"
			          << std::setw(10) << "RAM (MB)" << std::endl;
			std::cout << "--------------------------------------------------\n";

			int count = std::min(30, static_cast<int>(processes.size()));
			for (int i = 0; i < count; ++i) {
				const auto& proc = processes[i];
				double memoryMB = proc.memory / 1024.0;

				std::string displayName = proc.name;
				if (displayName.length() > 29) {
					displayName = displayName.substr(0, 29);
				}
				if (memoryMB > 1024) {
					color(5);
				} else {
					if (memoryMB > 512) {
						color(12);
					} else {
						if (memoryMB > 256) {
							color(6);
						} else {
							if (memoryMB > 128) {
								color(10);
							} else {
								if (memoryMB > 64) {
									color(3);
								} else {
									if (memoryMB > 32) {
										color(9);
									} else {
										color(5);
									}
								}
							}
						}
					}
				}
				std::cout << std::left << std::setw(6) << proc.pid
				          << std::setw(32) << displayName
				          << std::setw(10) << std::fixed << std::setprecision(2) << memoryMB << std::endl;
			}
			color(8);
			std::cout << "==================================================\n";
			color(7);
			std::cout << "Press 'q' exit monitor\n";
		}

		bool checkForExit() {
			return _kbhit() && _getch() == 'q';
		}

		void run(int interval = 3) {
			std::cout << "Start monitor system RAM using..." << std::endl;
			std::cout << "Clear time: " << interval << " seconds" << std::endl;
			std::cout << "Preds 'q'  exit monitor" << std::endl;
			std::cout << "Collecting progress information..." << std::endl;
			Sleep(2000);

			while (true) {
				scanProcesses();
				displayTopProcesses();

				if (checkForExit()) {
					break;
				}

				Sleep(interval * 1000);
			}

			std::cout << "Monitor program is exiting..." << std::endl;
		}
};

int main() {
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_CURSOR_INFO cursorInfo;
	GetConsoleCursorInfo(handle, &cursorInfo);
	cursorInfo.bVisible = false;
	SetConsoleCursorInfo(handle, &cursorInfo);
	DeleteMenu(GetSystemMenu(GetConsoleWindow(), FALSE), SC_CLOSE, MF_BYCOMMAND);
	DrawMenuBar(GetConsoleWindow());
	system("mode con cols=50 lines=38");
	ProcessMonitor monitor;
	monitor.run(1); // 每3秒刷新一次
	return 0;
}
